/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.etrs.formathlon.metier.utils.email;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import java.util.List;
import net.etrs.formathlon.entity.formation.Inscription;
import net.etrs.formathlon.entity.formation.Session;
import net.etrs.formathlon.entity.utilisateur.Personnel;
import net.etrs.formathlon.entity.utilisateur.Utilisateur;
import net.etrs.formathlon.metier.utils.DateUtils;
import net.etrs.formathlon.metier.utils.constantes.Parametres;
import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.DateTime;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.property.Description;
import net.fortuna.ical4j.model.property.DtEnd;
import net.fortuna.ical4j.model.property.DtStart;
import net.fortuna.ical4j.model.property.Method;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.Summary;
import net.fortuna.ical4j.model.property.Uid;
import net.fortuna.ical4j.model.property.Version;
import net.fortuna.ical4j.util.CompatibilityHints;
import org.apache.commons.mail.EmailAttachment;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;

/**
 * Classe qui va gérer les différents envoies de mail de l'application
 * @author OPIF
 */
@Stateless
public class MailManager {

    /**
     * Methode qui envoie un mail d'information lors du passage de la liste secondaire
     * à la liste principale pour une cession. Cette état c'existe pas. On calcul les listes
     * en prennant les X premiers parmis les validés ou x est le nombre de place max dans 
     * la cession.
     * @param inscription 
     */
    public static void envoieModificationInscription(Inscription inscription) throws EmailException {
        String sujet = "Passage sur la liste principal";
        // set the html message
        String message = String.format(
                "Vous faites maintenant parti de la liste principale pour la formation \'%s\' du %s",
                inscription.getSession().getFormation().getLibelle(),
                DateUtils.getDateFormatee(inscription.getSession().getDateDebut()));

        Collection<String> listTo = new HashSet<String>();
        listTo.add(inscription.getPersonnel().getUtilisateur().getMail());

        envoiMail(sujet, message, listTo, newICalFile(inscription.getSession()));
    }

    /**
     * Methode qui un mail de refus de l'inscription par un des deux valideurs.
     * @param inscription
     * @throws EmailException 
     */
    public static void envoiRefusInscription(Inscription inscription) throws EmailException {
        String sujet = "Demande de Formation refusée.";

        // set the html message
        String message = String.format(
                "Votre demande pour la formation %s du %s à été refusée.",
                inscription.getSession().getFormation().getLibelle(),
                DateUtils.getDateFormatee(inscription.getSession().getDateDebut()));

        List<String> listTo = new ArrayList<String>();
        listTo.add(inscription.getPersonnel().getUtilisateur().getMail());

        envoiMail(sujet, message, listTo, null);
    }

    /**
     * Methode qui envoie aux inscrits les informations
     * @param session
     * @throws EmailException 
     */
    public static void envoiInformationSession(Session session) throws EmailException {

        String sujet = String.format("Inscription à une formation de %s", session.getFormation().getLibelle());
        // set the html message
        String messageListPrinc = String.format(
                "Votre êtes inscrit sur la liste principale pour la formation %s du %s",
                session.getFormation().getLibelle(),
                DateUtils.getDateFormatee(session.getDateDebut()));
        String messageListSec = String.format(
                "Votre êtes inscrit sur la liste secondaire pour la formation %s du %s",
                session.getFormation().getLibelle(),
                DateUtils.getDateFormatee(session.getDateDebut()));

        Collection<String> listToPrinc = new HashSet<String>();
        Collection<String> listToSec = new HashSet<String>();

        int compteur = 0;
        for (Inscription inscription : session.getListInscription()) {
            if (inscription.getEtat().equals(Inscription.Etat.VALIDEE_DIVISION)) {
                if (compteur < session.getNbPlaceMax()) {
                    listToPrinc.add(inscription.getPersonnel().getUtilisateur().getMail());
                    compteur++;
                } else {
                    listToSec.add(inscription.getPersonnel().getUtilisateur().getMail());
                }
            }
        }

        if (!listToPrinc.isEmpty()) {
            envoiMail(sujet, messageListPrinc, listToPrinc, newICalFile(session));
        }

        if (!listToSec.isEmpty()) {
            envoiMail(sujet, messageListSec, listToSec, null);
        }

    }

    /**
     * Methode synchronizes d'envoi de mail.
     * @param sujet
     * @param message
     * @param listTo
     * @param cheminICAL
     * @throws EmailException 
     */
    private static synchronized void envoiMail(String sujet, String message, Collection<String> listTo, String cheminICAL) throws EmailException {
        // Create the email message
        HtmlEmail email = new HtmlEmail();

        email.setHostName(Parametres.ADRESSE_SERVEUR_SMTP);

        email.setFrom(Parametres.ADRESSE_MAIL_APPLICATION, "Formathlon Information");
        email.setSubject(sujet);

        email.setHtmlMsg(String.format("<html><body>%s</body></html>", message));
        // set the alternative message
        email.setTextMsg(message);

        for (String adrMail : listTo) {
            email.addTo(adrMail);
        }

        if (cheminICAL != null) {
            // Create the attachment
            EmailAttachment attachment = new EmailAttachment();
            attachment.setPath(cheminICAL);
            attachment.setDisposition(EmailAttachment.ATTACHMENT);
            attachment.setDescription("Session Formathlon");
            attachment.setName("session.ics");

            email.attach(attachment);
        }
        email.send();
    }

    /**
     * Envoie d'un mail a chaque chef de cours et chef de division des personnels
     * qui ont suivie la formation pour leurs en informer.
     * @param mailParticipation composant détenant la liste des destinataires et des participants.
     * @throws EmailException 
     */
    public static void envoiRapportFinSession(MailParticipationDTO mailParticipation) throws EmailException {
        //session concernée
        Session session = mailParticipation.getSession();
        
         String sujet = String.format("Rapport de partitipation à la formation ", session.getFormation().getLibelle());
       List<String> listTo = new ArrayList<String>();
        
        //l'ensemble des destinataires (chef/adjoint, cours/div)
        for (Utilisateur destinataire : mailParticipation.getDestinataires().keySet()) {
            listTo.clear(); 
            listTo.add(destinataire.getMail());
            StringBuilder sb = new StringBuilder();
            sb.append("Etat des partitipations des subordonnées : \r\n");
            //l'ensemble des subordonnés du destinataire
            for (Personnel subordonne : mailParticipation.getDestinataire(destinataire).getListParticipationSubordonne().keySet()) {
                sb.append(subordonne.getNomComplet());
                //vrai si le subordonné a participé à la session
                if (mailParticipation.getDestinataire(destinataire).getParticipation(subordonne)) {
                    sb.append(" : PRESENT\r\n");    
                } else {
                    sb.append(" : NON PRESENT\r\n");
                }
                

            }
            envoiMail(sujet, sb.toString(), listTo, null);
        }
    }

    /**
     * Crée un nouveau fichier ICal et retourne son emplacement.
     * @return 
     */
    private static synchronized String newICalFile(Session session) {

        CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_OUTLOOK_COMPATIBILITY, true);

        VEvent vEvent = new VEvent();
        vEvent.getProperties().add(new Uid("Formathlon"));
        vEvent.getProperties().add(new Summary(session.getFormation().getLibelle()));
        vEvent.getProperties().add(new Description(session.getFormation().getDescription()));
        vEvent.getProperties().add(new DtStart(new DateTime(session.getDateDebut())));
        vEvent.getProperties().add(new DtEnd(new DateTime(session.getDateFin())));

        Calendar cal = new Calendar();
        cal.getProperties().add(new ProdId("-//Formathlon//OPIF//FR"));
        cal.getProperties().add(Version.VERSION_2_0);
        cal.getProperties().add(Method.PUBLISH);
        cal.getComponents().add(vEvent);


        //on va chercher le chemin et le nom du fichier et on me tout ca dans un String
        String adressedufichier = System.getProperty("user.dir") + "/rdv.ics";

        BufferedWriter output = null;
        try {
            FileWriter fw = new FileWriter(adressedufichier, false);
            output = new BufferedWriter(fw);
            // output.write(contenu.toString());
            output.write(cal.toString());

        } catch (IOException ex) {
            Logger.getLogger(MailManager.class.getCanonicalName()).log(Level.SEVERE, null, ex);

        } finally {
            if (output != null) {

                try {
                    output.flush();
                    output.close();
                } catch (IOException ex) {
                    Logger.getLogger(MailManager.class.getCanonicalName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        return adressedufichier;
    }

    /**
     * Après verrouillage de l'instructeur envoi de mail aux personnes en liste complémentaire.
     * @param listeComplementaire 
     */
    public static void envoiAnnulationListeComplementaire(Session session, List<Utilisateur> listeComplementaire) throws EmailException {
        String sujet = "Session verrouillée";
        // set the html message
        String message = String.format(
                "Votre inscription en liste d'attente pour la formation %s du %s à été annulée.",
                session.getFormation().getLibelle(),
                DateUtils.getDateFormatee(session.getDateDebut()));

        Collection<String> listTo = new HashSet<String>();

        for (Utilisateur utilisateur : listeComplementaire) {
            listTo.add(utilisateur.getMail());
        }
        envoiMail(sujet, message, listTo, null);
    }

    public static void envoiAnnulationSession(Session session) throws EmailException {
        //s'l y a au moins une inscription à annuler
        if (session.getListInscription().size() > 1) {
            String sujet = "Session annulée";
            // set the html message
            String message = String.format(
                    "Par manque de participant pour la formation %s du %s la session à été annulée.",
                    session.getFormation().getLibelle(),
                    DateUtils.getDateFormatee(session.getDateDebut()));

            Collection<String> listTo = new HashSet<String>();

            for (Inscription inscription : session.getListInscription()) {
                listTo.add(inscription.getPersonnel().getUtilisateur().getMail());
            }

            envoiMail(sujet, message, listTo, null);
        }
    }

    public static void envoiSuppressionSession(Session session) throws EmailException {
        String sujet = "Session supprimée";
        // set the html message
        String message = String.format(
                "La formation %s du %s a été supprimée.",
                session.getFormation().getLibelle(),
                DateUtils.getDateFormatee(session.getDateDebut()));

        Collection<String> listTo = new HashSet<String>();

        for (Inscription inscription : session.getListInscription()) {
            listTo.add(inscription.getPersonnel().getUtilisateur().getMail());
        }
        envoiMail(sujet, message, listTo, null);
    }
}
